import sys
from confs import EBV_LEARNING_RATE, EBV_SHARP_ADDITION, EBV_EPS
from ebv_iterate_utils import read_stats

class Cache:
    def __init__(self, keyname, max_len):
        self.d = {}
        self.keyname = keyname
        self.max_len = max_len
        self.hit = 0
        self.tot = 0

    MAX_SIZE = 100000

    def emit(self, key, val):
        self.tot += 1

        if len(key) > self.max_len:
            self.out(key, val)
            return

        if key in self.d:
            self.hit += 1
            self.d[key] += val
        else:
            self.d[key] = val

        if len(self.d) > Cache.MAX_SIZE:
            self.flush()

    def out(self, word, value):
        print '%s\t%s:%s' % (word, self.keyname, value.hex())

    def flush(self):
        for key, val in self.d.items():
            self.out(key, val)
        self.d = {}

    def stat(self):
        print >> sys.stderr, '[debug] %s hit rate: %.2f' % (self.keyname, 1.0 * self.hit / self.tot)

def main():
    '''
    input: ebv_iteration_<i-1>.txt where i is current iteration id
    (word, '<'? '>'? lbv rbv degl degr llinkees.. rlinkees..) -> (llinkee, 'lbv+:' lbv / degl * LEARNING_RATE)..
                                                                 (rlinkee, 'rbv+:' rbv / degr * LEARNING_RATE)..
                                                                 (word, 'lbv+:' lbv * (1 - LEARNING_RATE))
                                                                 (word, 'rbv+:' rbv * (1 - LEARNING_RATE))
                                                                 (word, '<'? '>'? degl degr llinkees.. rlinkees..)
                                                                 # if word hypothesis eviction condition is satisfied:
                                                                 (llinkee, 'r-:'word)..
                                                                 (rlinkee, 'l-:'word)..
    '''
    words, sharpls, sharprs = read_stats()
    lcache = Cache('lbv+', 6)
    rcache = Cache('rbv+', 11)
    evicts = 0
    for line in sys.stdin:
        line = line.strip()
        tokens = line.split()
        word = tokens[0]
        sharpl = sharpr = False
        lbv = rbv = 1.0 / words
        for token in tokens[1: ]:
            if ':' in token:
                key, val = token.split(':')
            else:
                key = token
            if key == 'lbv':
                lbv = float.fromhex(val)
            elif key == 'rbv':
                rbv = float.fromhex(val)
            elif key == 'degl':
                degl = int(val)
            elif key == 'degr':
                degr = int(val)
            elif key == '<':
                sharpl = True
            elif key == '>':
                sharpr = True
            elif key == 'l':
                receiver = val
                rcache.emit(receiver, lbv / degl * EBV_LEARNING_RATE)
            elif key == 'r':
                receiver = val
                lcache.emit(receiver, rbv / degr * EBV_LEARNING_RATE)

        # delete a word
        if lbv * rbv < EBV_EPS / words ** 2: 
            evicts += 1
            for token in tokens[1: ]:
                if ':' in token:
                    key, val = token.split(':')
                    if key == 'l':
                        print '%s\tr-:%s' % (val, word)
                    elif key == 'r':
                        print '%s\tl-:%s' % (val, word)
            continue

        if sharpl:
            lcache.emit(word, EBV_SHARP_ADDITION)
        if sharpr:
            rcache.emit(word, EBV_SHARP_ADDITION)
        lcache.emit(word, lbv * (1.0 - EBV_LEARNING_RATE) if degl else lbv)
        rcache.emit(word, rbv * (1.0 - EBV_LEARNING_RATE) if degr else rbv)
        print '%s\t%s' % (word, ' '.join(filter(lambda token: not token.startswith('lbv') and not token.startswith('rbv'), tokens[1: ]))) # the links
    lcache.flush()
    rcache.flush()
    lcache.stat()
    rcache.stat()
    print >> sys.stderr, '[debug] evicts:', evicts

if __name__ == '__main__':
    main()
